/*! \file
 * \brief Enter a brief description here.
 *
 * Enter a detailed description here. (optional)
 * \author Author (Ivo Wingelaar)
 * \date Date (2011)
 * \version Version (0.0.1)
 * \copyright Copyright (GNU LGPL v3)
 */

#include "LynxTimeManagerWindows_C.hpp"

#ifdef _LYNX_WINDOWS_

namespace Lynx
{

/** default constructor **/
TimeManagerWindows_C::TimeManagerWindows_C() :
    mHighPerformanceFreq(0),
    mHighPerformanceTimerSupport(FALSE),
    mMultiCore(FALSE)
{
    init_timer();
}

/** default destructor **/
TimeManagerWindows_C::~TimeManagerWindows_C()
{
    //
}

/** virtual function **/
/** init_timer       **/
//! Initializes the timer.
/// \return void
/// \param  void
void TimeManagerWindows_C::init_timer(void)
{
    // disable hires timer on multiple core systems, bios bugs result in bad hires timers.
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    mMultiCore = (sysinfo.dwNumberOfProcessors > 1);
    mHighPerformanceTimerSupport = QueryPerformanceFrequency(&mHighPerformanceFreq);
    init_virtual_timer();
}

/** const virtual function **/
/** get_real_time          **/
//! Returns the real time, depends on implementation.
/// \return uint32_t
///         The real time.
/// \param  void
uint32_t TimeManagerWindows_C::get_real_time(void) const
{
    if(mHighPerformanceTimerSupport)
    {
        // Avoid potential timing inaccuracies across multiple cores by
        // temporarily setting the affinity of this process to one core.
        DWORD_PTR affinityMask;
        if(mMultiCore)
            affinityMask = SetThreadAffinityMask(GetCurrentThread(), 1);
        LARGE_INTEGER nTime;
        BOOL queriedOK = QueryPerformanceCounter(&nTime);

        // Restore the true affinity.
        if(mMultiCore)
            (void)SetThreadAffinityMask(GetCurrentThread(), affinityMask);

        if(queriedOK)
            return uint32_t((nTime.QuadPart) * 1000 / mHighPerformanceFreq.QuadPart);

    }
    return GetTickCount();
}

} // namespace Lynx

#endif // _LYNX_WINDOWS_
